﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace Murry.Security
{
    internal static class ConnectionsFile
    {
        public static List<ConnectionInfo> Load(string path = "connections.config")
        {
            if (String.IsNullOrWhiteSpace(path))
            {
                throw new ArgumentNullException("path");
            }

            if (!File.Exists(path))
            {
                throw new FileNotFoundException("File not found.", path);
            }

            try
            {
                using (var reader = XmlReader.Create(path))
                {
                    var serializer = new XmlSerializer(typeof(List<ConnectionInfo>));

                    return (List<ConnectionInfo>) serializer.Deserialize(reader) ;
                }
            }
            catch (InvalidOperationException)
            {
                var bytes = File.ReadAllBytes(path);

                var entropy = Password.HashAsBytes(Path.GetFileName(path));
                var decryptedBytes = ProtectedData.Unprotect(bytes, entropy, DataProtectionScope.CurrentUser);

                using (var memStream = new MemoryStream(decryptedBytes))
                using (var reader = XmlReader.Create(memStream))
                {
                    var serializer = new XmlSerializer(typeof(List<ConnectionInfo>));

                    return (List<ConnectionInfo>)serializer.Deserialize(reader);
                }
            }
        }

        public static void Save(List<ConnectionInfo> connections, string path = "connections.config", bool protect = true)
        {
            if (connections == null)
            {
                throw new ArgumentNullException("connections");
            }

            if (String.IsNullOrWhiteSpace(path))
            {
                throw new ArgumentNullException("path");
            }

            using(var memStream = new MemoryStream())
            using (var writer = XmlWriter.Create(memStream))
            {
                var serializer = new XmlSerializer(typeof(List<ConnectionInfo>));

                serializer.Serialize(writer, connections);

                byte[] bytes = null;

                if (!protect)
                {
                    bytes = memStream.GetBuffer();
                }
                else
                {
                    var entropy = Password.HashAsBytes(Path.GetFileName(path));
                    bytes = ProtectedData.Protect(memStream.GetBuffer(), entropy, DataProtectionScope.CurrentUser);
                }

                using (var file = File.OpenWrite(path))
                {
                    file.Write(bytes, 0, bytes.Count());
                }
            }
        }
    }
}
